using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using iPhOwa.Exchange;
using iPhOwa.Web.Properties;

namespace iPhOwa.Web
{
	/// <summary>
	/// Base class for all project pages.
	/// </summary>
	[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Owa")]
	[SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly")]
	[SuppressMessage("Microsoft.Naming", "CA1706:ShortAcronymsShouldBeUppercase")]
	public class iPhOwaPage : Page
	{
		/// <summary>
		/// Name of the password cookie
		/// </summary>
		protected const string PasswordCookie = "iPhOwaPassword";

		/// <summary>
		/// Name of the username cookie.
		/// </summary>
		protected const string UserNameCookie = "iPhOwaUsername";

        /// <summary>
        /// Name of the useremail cookie
        /// </summary>
        protected const string UserEmailCookie = "iPhOwaUseremail";

		/// <summary>
		/// Determines if we need to auth for this page.
		/// </summary>
		protected virtual bool IsSecurePage
		{
			get { return true; }
		}

		/// <summary>
		/// The current session.
		/// </summary>
		[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Owa")]
		public OwaSession OwaSession
		{
			get { return new OwaSession(AuthenticationType, UserNameWithoutDomain, Password, Domain, OwaCookies); }
		}

		/// <summary>
		/// The configured authentication type.
		/// </summary>
		public static AuthenticationType AuthenticationType
		{
			get { return (AuthenticationType)Enum.Parse(typeof(AuthenticationType), Settings.Default.AuthenticationType); }
		}

		/// <summary>
		/// Path query string variable.
		/// </summary>
		public Uri Path
		{
			get
			{
				string pathProperty = Request["path"];

				return (!string.IsNullOrEmpty(pathProperty)) ? new Uri(pathProperty) : null;
			}
		}

		/// <summary>
		/// The cookies provided by OWA.
		/// </summary>
		[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Owa")]
		protected CookieContainer OwaCookies
		{
			get { return (CookieContainer)Session["OwaCookies"]; }
			set { Session["OwaCookies"] = value; }
		}

		/// <summary>
		/// The logged in users password, only store when doing basic authentication.
		/// </summary>
		protected string Password
		{
			get { return (string)Session["Password"]; }
			set
			{
				if(AuthenticationType == AuthenticationType.Basic)
				{
					Session["Password"] = value;
				}
			}
		}

		/// <summary>
		/// The logged in username.
		/// </summary>
		protected string UserName
		{
			get { return (string)Session["Username"]; }
			set { Session["Username"] = value; }
		}

        /// <summary>
        /// The logged in users email address
        /// </summary>
        protected string UserEmail
        {
            get { return (string)Session["Useremail"]; }
            set { Session["Useremail"] = value; }
        }

		/// <summary>
		/// The logged in users domain
		/// </summary>
		protected string Domain
		{
			get { return (UserName.Contains(@"\")) ? UserName.Split('\\')[0] : string.Empty; }
		}

		/// <summary>
		/// The logged in username with the domain removed.
		/// </summary>
		public string UserNameWithoutDomain
		{
			get { return (UserName.Contains(@"\")) ? UserName.Split('\\')[1] : UserName; }
		}

        /// <summary>
        /// The user email prefix
        /// </summary>
        public string UserEmailWithoutDomain
        {
            get { return (UserEmail.Contains("@")) ? UserEmail.Split('@')[0] : UserEmail; }
        }

        /// <summary>
        /// The Users OWA Folder Name
        /// </summary>
        public string UserFolder
        {
            get { return (Settings.Default.EmailRequired) ? UserEmailWithoutDomain : UserName; }
        }

		/// <summary>
		/// The OWA base URL for this user.
		/// </summary>
		public Uri BaseUrl
		{
            get { return new Uri(Settings.Default.OwaUrl, new Uri(string.Format(CultureInfo.InvariantCulture, "{0}/", UserFolder), UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA inbox URL for this user.
		/// </summary>
		public Uri InboxUrl
		{
			get { return new Uri(BaseUrl, new Uri("Inbox/", UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA calendar URL for this user.
		/// </summary>
		public Uri CalendarUrl
		{
			get { return new Uri(BaseUrl, new Uri("Calendar/", UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA notes URL for this user.
		/// </summary>
		public Uri NotesUrl
		{
			get { return new Uri(BaseUrl, new Uri("Notes/", UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA tasks URL for this user.
		/// </summary>
		public Uri TasksUrl
		{
			get { return new Uri(BaseUrl, new Uri("Tasks/", UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA contacts URL for this user.
		/// </summary>
		public Uri ContactsUrl
		{
			get { return new Uri(BaseUrl, new Uri("Contacts/", UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA deleted items URL for this user.
		/// </summary>
		public Uri DeletedItemsUrl
		{
			get { return new Uri(BaseUrl, new Uri("Deleted%20Items/", UriKind.Relative)); }
		}

		/// <summary>
		/// The OWA drafts URL for this user.
		/// </summary>
		public Uri DraftsUrl
		{
			get { return new Uri(BaseUrl, new Uri("Drafts/", UriKind.Relative)); }
		}

		/// <summary>
		/// Url new mail is submitted to.
		/// </summary>
		public Uri MailSubmissionUrl
		{
			get { return new Uri(BaseUrl, new Uri("%23%23DavMailSubmissionURI%23%23/", UriKind.Relative)); }
		}

		///<summary>
		/// Raises the <see cref="E:System.Web.UI.Control.Init"></see> event to initialize the page.
		///</summary>
		///<param name="e">An <see cref="T:System.EventArgs"></see> that contains the event data.</param>
		protected override void OnInit(EventArgs e)
		{
			base.OnInit(e);

			if(IsSecurePage)
			{
				if(string.IsNullOrEmpty(UserName) || !User.Identity.IsAuthenticated)
				{
					FormsAuthentication.RedirectToLoginPage();
					Response.End();
				}
			}
		}

		/// <summary>
		/// Expire a specific cookie.
		/// </summary>
		protected void ExpireCookie(string name)
		{
			if(Response != null && Response.Cookies != null && Response.Cookies[name] != null)
			{
				Response.Cookies[name].Expires = DateTime.Now.AddDays(-30);
			}
		}

		/// <summary>
		/// Set a cookie.
		/// </summary>
		protected void SetCookie(string name, string value)
		{
			var usernameCookie = new HttpCookie(name, value)
			                     	{
			                     			Expires = DateTime.Now.AddDays(Settings.Default.CookieEpirationDays)
			                     	};

			Response.Cookies.Add(usernameCookie);
		}

		/// <summary>
		/// Get a cookie.
		/// </summary>
		protected string GetCookie(string name)
		{
			HttpCookie cookie = Request.Cookies[name];

			return (cookie != null) ? cookie.Value : null;
		}

		/// <summary>
		/// Turn plain text email description into formatted HTML description with detected links.
		/// </summary>
		/// <param name="textDescription"></param>
		/// <returns></returns>
		protected static string BuildHtmlDescription(string textDescription)
		{
			string html = null;

			if(!string.IsNullOrEmpty(textDescription))
			{
				html = textDescription.Trim();

				// remove mailto:
				html = html.Replace(@"mailto:", string.Empty);

				// detect email address and make them clickable
				html = Regex.Replace(html, @"([0-9a-z_+\-\.]+@[0-9a-z\-\.]+\.[0-9a-z\-\.]+)", @"<a href=""ComposeMessage.aspx?to=$1"">$1</a>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

				// detect urls and make them clickable
				const string supportedUrlCharacters = @"0-9a-z+\.\-_&%/\?=:,";
				html = Regex.Replace(html, @"(https?://[" + supportedUrlCharacters + "]+)", @"<a href=""$1"">$1</a>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
				html = Regex.Replace(html, @"(\s+)(www.[" + supportedUrlCharacters + "]+)", @"$1<a href=""http://$2"">$2</a>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

				// clean up exessive new lines
				html = Regex.Replace(html, @"\s*\r\n(\s*\r\n\s*)+", @"<br/><br/>", RegexOptions.IgnoreCase | RegexOptions.Compiled);

				// replace newlines with html line breaks
				html = Regex.Replace(html, @"\r\n", @"<br/>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
			}

			return html;
		}
	}
}